﻿#region zh-CHS 2006 - 2007 DemoSoft 团队 | en 2006 - 2007 DemoSoft Team

//     NOTES
// ---------------
//
// This file is a part of the G.O.S.E(Game Online Server Engine) for .NET.
//
//                 2006-2007 DemoSoft Team
//
//
// First Version : by H.Q.Cai - mailto:caihuanqing@hotmail.com

/***************************************************************************
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU Lesser General Public License as published
 *   by the Free Software Foundation; either version 2.1 of the License, or
 *   (at your option) any later version.
 *
 ***************************************************************************/

#region zh-CHS 包含名字空间 | en Include namespace
using System;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Collections.Generic;
using Demo_G.O.S.E.ServerEngine.Util;
using Demo_G.O.S.E.ServerEngine.Item;
using Demo_G.O.S.E.ServerEngine.Common;
using Demo_G.O.S.E.ServerEngine.Network;
using Demo_G.O.S.E.ServerEngine.Creature;
#endregion

namespace Demo_G.O.S.E.ServerEngine.Map
{
    /// <summary>
    /// 地图内某个部分的内容及信息(Clients,Mobiles,Items)
    /// </summary>
    public class Sector : IPoint2D, IComparable, IComparable<Sector>
    {
        #region zh-CHS 构造和初始化和清理 | en Constructors and Initializers and Dispose
        /// <summary>
        /// 
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="owner"></param>
        internal Sector( long pointX, long pointY, long iSize, BaseMap owner )
        {
            m_X = pointX;
            m_Y = pointY;
            m_Size = iSize;
            m_Owner = owner;

            m_RectBound = new Rectangle2D( m_X, m_Y, m_Size, m_Size );
        }
        #endregion

        #region zh-CHS 共有属性 | en Public Properties

        #region zh-CHS ItemsToArray 方法 | en ItemsToArray Methods
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 空数组
        /// </summary>
        BaseCreature[] s_ZeroBaseMobileArray = new BaseCreature[0];
        /// <summary>
        /// 怪物/NPC的列表
        /// </summary>
        private List<BaseCreature> m_Mobiles = new List<BaseCreature>();
        /// <summary>
        /// 怪物/NPC的锁
        /// </summary>
        private ReaderWriterLockSlim m_LockMobiles = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 地图点内的所有人物(npc/playes/monster)数量
        /// </summary>
        public long MobilesCount
        {
            get { return m_Mobiles.Count; }
        }

        /// <summary>
        /// 地图点内的所有人物(npc/playes/monster)数组
        /// </summary>
        /// <returns></returns>
        public BaseCreature[] MobilesToArray()
        {
            BaseCreature[] baseMobileArray = s_ZeroBaseMobileArray;

            ReaderWriterLockSlimEx.EnterReadLock( m_LockMobiles );
            {
                baseMobileArray = m_Mobiles.ToArray();
            }
            ReaderWriterLockSlimEx.ExitReadLock( m_LockMobiles );

            return baseMobileArray;
        }
        #endregion

        #region zh-CHS ItemsToArray 方法 | en ItemsToArray Methods
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 空数组
        /// </summary>
        private BaseItem[] s_ZeroBaseItemArray = new BaseItem[0];
        /// <summary>
        /// 道具的列表
        /// </summary>
        private List<BaseItem> m_Items = new List<BaseItem>();
        /// <summary>
        /// 道具的锁
        /// </summary>
        private ReaderWriterLockSlim m_LockItems = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 地图点内的所有道具数量
        /// </summary>
        public long ItemsCount
        {
            get { return m_Items.Count; }
        }

        /// <summary>
        /// 地图点内的所有道具数组
        /// </summary>
        /// <returns></returns>
        public BaseItem[] ItemsToArray()
        {
            BaseItem[] baseItemArray = s_ZeroBaseItemArray;

            ReaderWriterLockSlimEx.EnterReadLock( m_LockItems );
            {
                baseItemArray = m_Items.ToArray();
            }
            ReaderWriterLockSlimEx.ExitReadLock( m_LockItems );

            return baseItemArray;
        }
        #endregion

        #region zh-CHS ClientsToArray 方法 | en ClientsToArray Methods
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 空数组
        /// </summary>
        NetState[] s_ZeroNetStateArray = new NetState[0];
        /// <summary>
        /// 客户端的列表
        /// </summary>
        private List<NetState> m_Clients = new List<NetState>();
        /// <summary>
        /// 客户端的锁
        /// </summary>
        private ReaderWriterLockSlim m_LockClients = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 地图点内的所有客户端数量
        /// </summary>
        public long ClientsCount
        {
            get { return m_Clients.Count; }
        }

        /// <summary>
        /// 地图点内的所有客户端数组
        /// </summary>
        /// <returns></returns>
        public NetState[] ClientsToArray()
        {
            NetState[] netStateArray = s_ZeroNetStateArray;

            ReaderWriterLockSlimEx.EnterReadLock( m_LockClients );
            {
                netStateArray = m_Clients.ToArray();
            }
            ReaderWriterLockSlimEx.ExitReadLock( m_LockClients );

            return netStateArray;
        }
        #endregion


        #region zh-CHS PlayersToArray 方法 | en PlayersToArray Methods
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 地图点内的所有玩家
        /// </summary>
        private List<BaseCreature> m_Players = new List<BaseCreature>();
        /// <summary>
        /// 地图点内的所有玩家的锁
        /// </summary>
        private ReaderWriterLockSlim m_LockPlayers = new ReaderWriterLockSlim();
        #endregion
        /// <summary>
        /// 地图点内的所有玩家数量
        /// </summary>
        public long PlayersCount
        {
            get { return m_Players.Count; }
        }

        /// <summary>
        /// 地图点内所有的玩家数组
        /// </summary>
        /// <returns></returns>
        public BaseCreature[] PlayersToArray()
        {
            BaseCreature[] baseMobileArray = s_ZeroBaseMobileArray;

            ReaderWriterLockSlimEx.EnterReadLock( m_LockPlayers );
            {
                baseMobileArray = m_Players.ToArray();
            }
            ReaderWriterLockSlimEx.ExitReadLock( m_LockPlayers );

            return baseMobileArray;
        }
        #endregion

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 当前的区域点如果有玩家的话就激活该区域点
        /// 如果没有玩家的话，无效此区域点
        /// </summary>
        private bool m_Active = false;
        #endregion
        /// <summary>
        /// 当前的区域点如果有玩家的话就激活该区域点(true)
        /// 如果没有玩家的话，无效此区域点(false)
        /// </summary>
        public bool Active
        {
            get { return m_Active; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 拥有者的地图
        /// </summary>
        private BaseMap m_Owner = null;
        #endregion
        /// <summary>
        /// 地图点的拥有者(地图)
        /// </summary>
        public BaseMap Owner
        {
            get { return m_Owner; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 当前的地图的X点
        /// </summary>
        private long m_X = -1;
        #endregion
        /// <summary>
        /// 当前的地图原点的X点
        /// </summary>
        public float X
        {
            get { return m_X; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 当前的地图的Y点
        /// </summary>
        private long m_Y = -1;
        #endregion
        /// <summary>
        /// 当前的地图原点的Y点
        /// </summary>
        public float Y
        {
            get { return m_Y; }
        }

        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 当前的地图点宽和高范围大小
        /// </summary>
        private long m_Size = 0;
        #endregion
        /// <summary>
        /// 当前的基于地图原点的范围大小
        /// </summary>
        public long Size
        {
            get { return m_Size; }
        }
        
        #region zh-CHS 私有成员变量 | en Private Member Variables
        /// <summary>
        /// 地图点的范围
        /// </summary>
        private Rectangle2D m_RectBound = new Rectangle2D( -1, -1, 0, 0 );
        #endregion
        /// <summary>
        /// 地图点的范围(原点+大小)
        /// </summary>
        public Rectangle2D Bound
        {
            get { return m_RectBound; }
        }

        #endregion

        #region zh-CHS 私有方法 | en Private Methods
        /// <summary>
        /// 难得用泛型 :)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="value"></param>
        private void Add<T>( List<T> listT, T valueT )
        {
            if ( listT == null )
            {
                Debug.WriteLine( "Sector.Add<T>(...) - listT == null error!" );
                return;
            }

            listT.Add( valueT );
        }

        /// <summary>
        /// 难得用泛型 :)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="value"></param>
        private void Remove<T>( List<T> listT, T valueT )
        {
            if ( listT == null )
            {
                Debug.WriteLine( "Sector.Remove<T>(...) - listT == null error!" );
                return;
            }

            listT.Remove( valueT );
        }

        /// <summary>
        /// 难得用泛型 :)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="list"></param>
        /// <param name="oldValue"></param>
        /// <param name="newValue"></param>
        private void Replace<T>( List<T> listT, T oldValue, T newValue )
        {
            if ( oldValue != null && newValue != null )
            {
                int index = ( listT != null ? listT.IndexOf( oldValue ) : -1 );

                if ( index >= 0 )
                    listT[index] = newValue;
                else
                    Add( listT, newValue );
            }
            else if ( oldValue != null )
                Remove( listT, oldValue );
            else if ( newValue != null )
                Add( listT, newValue );
        }
        #endregion

        #region zh-CHS 内部方法 | en Internal Methods
        /// <summary>
        /// 
        /// </summary>
        internal void Activate()
        {
            if ( m_Active == false )
            {
                m_Active = true;

                BaseItem[] baseItemArray = ItemsToArray();
                foreach ( BaseItem baseItem in baseItemArray )
                    baseItem.OnSectorActivate();

                BaseCreature[] baseMobileArray = MobilesToArray();
                foreach ( BaseCreature baseMobile in baseMobileArray )
                    baseMobile.OnSectorActivate();
            }
        }

        /// <summary>
        /// 
        /// </summary>
        internal void Deactivate()
        {
            if ( m_Active )
            {
                m_Active = false;

                BaseItem[] baseItemArray = ItemsToArray();
                foreach ( BaseItem baseItem in baseItemArray )
                    baseItem.OnSectorDeactivate();

                BaseCreature[] baseMobileArray = MobilesToArray();
                foreach ( BaseCreature baseMobile in baseMobileArray )
                    baseMobile.OnSectorDeactivate();
            }
        }
        #endregion

        #region zh-CHS 共有方法 | en Public Methods
        /// <summary>
        /// 
        /// </summary>
        /// <param name="oldState"></param>
        /// <param name="newState"></param>
        public void OnClientChange( NetState oldState, NetState newState )
        {
            ReaderWriterLockSlimEx.EnterWriteLock( m_LockClients );
            {
                Replace( m_Clients, oldState, newState );
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockClients );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="baseItem"></param>
        public void OnEnter( BaseItem baseItem )
        {
            ReaderWriterLockSlimEx.EnterWriteLock( m_LockItems );
            {
                Add( m_Items, baseItem );
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockItems );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="baseItem"></param>
        public void OnLeave( BaseItem baseItem )
        {
            ReaderWriterLockSlimEx.EnterWriteLock( m_LockItems );
            {
                Remove( m_Items, baseItem );
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockItems );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="baseMobile"></param>
        public void OnEnter( BaseCreature baseMobile )
        {
            ReaderWriterLockSlimEx.EnterWriteLock( m_LockMobiles );
            {
                Add( m_Mobiles, baseMobile );
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockMobiles );

            //if ( baseMobile.NetState != null )
            //{
            //    ReaderWriterLockSlimEx.EnterWriteLock( m_LockClients );
            //    {
            //        Add( m_Clients, baseMobile.NetState );
            //    }
            //    ReaderWriterLockSlimEx.ExitWriteLock( m_LockClients );
            //}

            //if ( baseMobile.Player )
            //{
            //    if ( m_Players.Count <= 0 )　// 如果游戏玩家的列表是空的话,则激活区域点,说明此区域点有玩家存在
            //        m_Owner.ActivateSectors( this );

            //    ReaderWriterLockSlimEx.EnterWriteLock( m_LockPlayers );
            //    {
            //        Add( m_Players, baseMobile );
            //    }
            //    ReaderWriterLockSlimEx.ExitWriteLock( m_LockPlayers );
            //}
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="baseMobile"></param>
        public void OnLeave( BaseCreature baseMobile )
        {
            ReaderWriterLockSlimEx.EnterWriteLock( m_LockMobiles );
            {
                Remove( m_Mobiles, baseMobile );
            }
            ReaderWriterLockSlimEx.ExitWriteLock( m_LockMobiles );

            //if ( baseMobile.NetState != null )
            //{
            //    ReaderWriterLockSlimEx.EnterWriteLock( m_LockClients );
            //    {
            //        Remove( m_Clients, baseMobile.NetState );
            //    }
            //    ReaderWriterLockSlimEx.ExitWriteLock( m_LockClients );
            //}

            //if ( baseMobile.Player && m_Players.Count > 0 )
            //{
            //    ReaderWriterLockSlimEx.EnterWriteLock( m_LockPlayers );
            //    {
            //        Remove( m_Players, baseMobile );
            //    }
            //    ReaderWriterLockSlimEx.ExitWriteLock( m_LockPlayers );

            //    if ( m_Players.Count <= 0 )　// 如果游戏玩家的列表是空的话,则无效区域点,说明此区域点玩家不存在
            //        m_Owner.DeactivateSectors( this );
            //}
        }
        #endregion

        #region zh-CHS 接口实现 | en Interface Implementation
        /// <summary>
        /// 
        /// </summary>
        /// <param name="otherBaseMap"></param>
        /// <returns></returns>
        public int CompareTo( Sector otherSector )
        {
            if ( otherSector == null )
                return 1;

            int iCompareX = m_X.CompareTo( otherSector.m_X );
            if ( iCompareX != 0 )
                return iCompareX;

            int iCompareY = m_Y.CompareTo( otherSector.m_Y );
            if ( iCompareY != 0 )
                return iCompareY;

            if ( m_Owner == null )
            {
                if ( otherSector.m_Owner == null )
                    return 0;
                else
                    return -1;
            }

            return m_Owner.CompareTo( otherSector.m_Owner );
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="xObject"></param>
        /// <returns></returns>
        public int CompareTo( object xObject )
        {
            return CompareTo( xObject as Sector );
        }
        #endregion
    }
}
#endregion

